package com.wxm.china.port.dds.task;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.wxm.china.port.dds.config.DdsProperties;
import com.wxm.china.port.dds.enm.ChinaPortDdsTypeEnum;
import com.wxm.china.port.dds.exception.DDSException;
import com.wxm.china.port.dds.utils.DdsR;
import com.wxm.china.port.dds.utils.OkHttpUtils;
import com.wxm.china.port.dds.vo.param.PayExInfoStrParam;
import com.wxm.china.port.dds.vo.result.DdsEntityResult;
import com.wxm.china.port.dds.vo.result.SignatureResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.time.format.DateTimeFormatter;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Function;

/**
 * <p>
 *     数据加签轮询定时器
 * </p>
 *
 * @author: wxm
 * @Date: 2023/6/29
 */
@Slf4j
@Component
public class DDsPollingTask implements SchedulingConfigurer {
    private static final DateTimeFormatter FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    @Value("${task.cron}")
    private String taskCorn;
    @Autowired
    private ThreadPoolExecutor executor;
    @Autowired
    private DdsProperties ddsProperties;
    @Value("${push-179-url}")
    public String push179Url;


    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(() -> {
            CompletableFuture.runAsync(()->{
                //得到需要加签的数据
                List<DdsEntityResult> list = this.sendGainUrl();

                //循环加签和返回
                if (list != null && list.size() > 0){
                    for (int i = 0; i < list.size(); i++) {
                        DdsEntityResult dds = list.get(i);
                        try {
                            if (ChinaPortDdsTypeEnum.T179.getCode().equals(dds.getType())){
                                //179上报
                                PayExInfoStrParam p = JSONObject.parseObject(dds.getReqValue(),PayExInfoStrParam.class);
                                //将一级参数使用||分割
                                String s =  "\"sessionID\":\"" + p.getSessionID() + "\"||" +
                                        "\"payExchangeInfoHead\":\"" + JSON.toJSONString(p.getPayExchangeInfoHead()) + "\"||" +
                                        "\"payExchangeInfoLists\":\"" + JSON.toJSONString(p.getPayExchangeInfoLists()) + "\"||" +
                                        "\"serviceTime\":\"" + p.getServiceTime() + "\"";
                                //进行加签
                                dds.setReqValue(s);
                                SignatureResult signatureResult = this.sendDdsUrl(dds, i);
                                //补全签名参数
                                p.setCertNo(signatureResult.getCertNo());
                                p.setSignValue(signatureResult.getSignatureValue());
                                //进行上报
                                String message = this.orderPush179(p);
                                //上报信息返回
                                this.sendGainNotifyUrl(dds.getId(),dds.getType(),message,null);
                            }else {
                                //进行加签
                                SignatureResult signature = this.sendDdsUrl(dds, i);
                                //加签返回
                                this.sendGainNotifyUrl(dds.getId(),dds.getType(),signature,null);
                            }
                        }catch (Exception e){
                            e.printStackTrace();
                            this.sendGainNotifyUrl(dds.getId(),dds.getType(),e.getMessage(),e.getMessage());
                        }
                    }
                }
            }, executor).exceptionally(e -> {
                log.error("加签轮询失败",e);
                throw new RuntimeException("加签轮询失败！" + e.getMessage());
            });
        }, triggerContext -> {
            CronTrigger cronTrigger = new CronTrigger(taskCorn);
            return cronTrigger.nextExecutionTime(triggerContext);
        });
    }


    /**
     * 发送获取加签数据请求
     * @return List<DdsEntityVo>
     */
    private List<DdsEntityResult> sendGainUrl(){
        log.info("开始请求加签数据");
        JSONObject param = new JSONObject();
        param.put("size",ddsProperties.getGainSize());
        return OkHttpUtils.sendGetParam(ddsProperties.getGainUrl(), param, DdsEntityResult.class, OkHttpUtils::resultArrayR);
    }

    /**
     * 发送加签请求
     * @param result 加签数据
     * @param i i
     * @return SignatureResult
     */
    private SignatureResult sendDdsUrl(DdsEntityResult result,int i){
        log.info("调用加签客户端 {} -> {}",i,result);
        JSONObject j = new JSONObject();
        j.put("id",result.getId());
        j.put("data",result.getReqValue());
        return OkHttpUtils.sendPostJson(ddsProperties.getUrl(),j,SignatureResult.class,OkHttpUtils::resultObjectR);
    }

    /**
     * 发送加签返回请求
     * @param id ID 请求的ID
     * @param type 类型 请求的类型
     * @param result result
     * @param errorMsg 失败说明
     */
    private <R,T> void sendGainNotifyUrl(Integer id, String type, R result,String errorMsg){
        log.info("加签数据{} 开始发送回调",StringUtils.hasText(errorMsg) ? "失败" : "成功");
        JSONObject j = new JSONObject();
        //将ID装入返回
        j.put("id",id);
        j.put("type",type);
        j.put("code", StringUtils.hasText(errorMsg) ? 500 : 200);
        j.put("result",result);
        OkHttpUtils.sendPostJson(ddsProperties.getNotifyUrl(), JSONObject.parseObject(JSONObject.toJSONString(DdsR.ok(j))), JSONObject.class, (res,clazz) -> JSONObject.parseObject(res));
    }

    /**
     * 179支付上报
     * @param p PayExInfoStrParam
     * @return String
     */
    private String orderPush179(PayExInfoStrParam p){
        log.info("开始上报179支付信息 sessionID：{}",p.getSessionID());
        JSONObject j = new JSONObject();
        j.put("payExInfoStr",JSONObject.parseObject(JSONObject.toJSONString(p), Feature.OrderedField));
        return OkHttpUtils.sendPostFormData(push179Url, j, String.class, (res,clazz) -> {
            JSONObject json = JSONObject.parseObject(res);
            String message = json.getString("message");
            if (!"10000".equals(json.getString("code"))){
                DDSException.error(message);
            }
            return message;
        });
    }

}
